

import Queue
import pluginManage
import threading
import settings

import urllib2

'''
All Major Inter-Thread communication is done using Queues, with a dedicated queue for each direction between the GUI and the web retreval thread.
	Note: web retrieval functions may generate more sub-threads, but that is doen entirely within the plugin, which is beyond the purview of the main aplication code.
	Therefore, plugin thread safety is the responsibility of the plugin programmer.

Qin	: webGetThread		-> GUI
Qerr	: webGetThread		-> GUI
Qout	: GUI			-> webGetThread

Qstate  : webSubThreads -> webGetThread


Various Commands:
	All commands are dictionaries. Commands are passed as {"commandNameString" : commandValue} Passing a dictionary as a command value is NOT uncommon
	All command names sould be fairly self-explanatory.
		webGetThread	-> GUI:

			Print Text to Status Window	 :   {"printText"	:   textToPrintStr}

			All progress-bar updates sould be handled by webFunctions.py Here they are for completeness:
				{"subProgressBar" : self.subBarValue, "subProgressBarTot" : self.subBarTot}
				{"mainProgressBar" : self.mainBarValue, "mainProgressBarTot" : self.mainBarTot}

			Errors are passed through Qerr using the same format:
			Print Error to Status Window	 :   {"printError"	:   textToPrintStr}
				Note: Errors are printed in red, and accompanied by a system Beep


		GUI			 -> webGetThread:
		The text strings passed with reach command, (Excepting the state commands) are set by the plugin itself in it's configuration variables (See pluginScaffold.py).
			Change Mode		:   {"chMode"   : pluginInstanceDictionary}	  #See changeGUIMode.py for configDict definition
			Set nameList File	:   {"listFile" : setOfNames}
			Set Overwrite Mode	:   {"ovwMode"  : textOfOverwriteMode}

			Start, stop		:   {"state" : "Pause"}
			or pause		:   {"state" : "Stop"}
			Retrieval		:   {"state" : "Go"}


		webGetThread  -> webSubThreads:
			Used only for pausing and stopping retrieval threads. Each command is a text string.

			NOTE: Can be ignored by plugins
				Pause		:   "pause"
				Stop		:   "stop"


		#TODO - A lot of this is not implemented correctly, or at all


Also, there is a function here that is never actually defined here, but in this namespace

Basically, on start, main.py defines a functinon called printFunc which is basically a simple alias for print
later on, GUIInit.py redefines it to a wx.function which writes to the main window.

It has to always be present, since the logger uses it, and the logger is a custom class and it doesnt seem to have any configuration variables, or any that are easy to add, anyways.
this way, It's hard-coded in the class def to simply write output to queVars.printFunc, and printFunc is simply redefined once the wx gui is ready to be able to actually
write strings to the gui

this way, dialogs printed during startup don't break anything, or vanish. They just go to the console untill the GUI is ready.
'''


def printFuncDef(inStr, color=(255, 255, 255)):
	print inStr,


printFunc = printFuncDef


Qin		=   Queue.Queue()
Qout		=   Queue.Queue()
Qerr		=   Queue.Queue()
Qstate		=   Queue.Queue()

pluginHandle = pluginManage.PluginHandler()

printToStdout		= False
logHasBeenInited	= False
threadLogHasBeenInited	= False

import cPickle
import wx


class ProgressBars:

		# ------------------------------------------------------------------ Dynamic Progress bar management:

	progBarLock		= threading.Lock()

	def setupSubProgressBars(self, mainWindow):
		self.parentWindow = mainWindow

		self.subProgressBars = {}
		self.subSizerIDs = {}
		self.subInfoText = {}

		self.subBarSizer = wx.BoxSizer(wx.HORIZONTAL)

		return self.subBarSizer

	def __addSubProgressBar(self, barID, barInfoString=None):

		self.progBarLock.acquire()

		itemSizer = wx.BoxSizer(wx.VERTICAL)

		subBar = wx.Gauge(self.parentWindow, -1, 100)

		if barInfoString:
			infoText = wx.StaticText(self.parentWindow, -1, "%s - %s" % (barID, barInfoString))
		else:
			infoText = wx.StaticText(self.parentWindow, -1, "%s - Unknown" % barID)

		itemSizer.Add(infoText, 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
		itemSizer.Add(subBar, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 5)

		self.subBarSizer.Add(itemSizer, 1, wx.EXPAND)

		self.subBarSizer.FitInside(self.parentWindow)

		self.subBarSizer.Layout()
		self.parentWindow.Layout()

		self.progBarLock.release()

		self.subProgressBars[barID] = subBar
		self.subInfoText[barID] = infoText
		self.subSizerIDs[barID] = itemSizer
		return barID


	def __removeSubProgressBar(self, progBarID):

		# for some reason, sizer.Remove() is not properly destroying child objects. Therefore, I have to actually track the
		# child objects, and manually call Destroy() on them

		self.subProgressBars.pop(progBarID).Destroy()
		self.subInfoText.pop(progBarID).Destroy()

		self.subBarSizer.Remove(self.subSizerIDs.pop(progBarID))

		self.parentWindow.Layout()

	def __incrementSubProgressBar(self, barID, ammount):
		bar = self.subProgressBars[barID]
		newValue = bar.GetValue() + ammount
		bar.SetValue(newValue)
		self.subInfoText[barID].SetLabel("%s - %d of %d" % (barID, newValue, bar.GetRange()))

	def __incrementMainProgressBar(self, ammount):
		bar = self.parentWindow.overallGauge
		current = bar.GetValue() + ammount
		bar.SetValue(current)

		self.parentWindow.mainProgressText.SetLabel("%s of %s Galleries" % (current, bar.GetRange()))

	def __setSubProgressBarLength(self, barID, length, value, infoString=None):
		bar = self.subProgressBars[barID]
		bar.SetRange(length)
		bar.SetValue(value)
		if infoString:
			self.subInfoText[barID].SetLabel("%s - %s" % (barID, infoString))
		else:
			self.subInfoText[barID].SetLabel("%s - %d of %d" % (barID, value, bar.GetRange()))


	def __pulseSubProgressBar(self, barID):
		self.subInfoText[barID].SetLabel("%s - Loading" % barID)
		self.subProgressBars[barID].Pulse()

	def __pulseMainProgressBar(self):

		self.parentWindow.overallGauge.Pulse()

	def __setupMainBar(self, barLength, position):
		self.parentWindow.overallGauge.SetRange(barLength)
		self.parentWindow.overallGauge.SetValue(position)

		self.parentWindow.mainProgressText.SetLabel("%s of %s Galleries" % (0, barLength))


	def addSubProgressBar(self, name=None):

		barID = threading.currentThread().name

		if not name:
			barInfoString = None
		else:
			barInfoString = name


		try:
			wx.CallAfter(self.__addSubProgressBar, barID, barInfoString)
		except:
			pass



	def removeSubProgressBar(self):
		barID = threading.currentThread().name
		try:
			wx.CallAfter(self.__removeSubProgressBar, barID)
		except:
			pass

	def pulseSubBar(self):
		barID = threading.currentThread().name
		try:
			wx.CallAfter(self.__pulseSubProgressBar, barID)
		except:
			pass


	def setSubBarLen(self, length, value=0, infoString=None):
		barID = threading.currentThread().name
		try:
			wx.CallAfter(self.__setSubProgressBarLength, barID, length, value, infoString)
		except:
			pass


	def incSubBar(self, ammount=1):
		barID = threading.currentThread().name
		try:
			wx.CallAfter(self.__incrementSubProgressBar, barID, ammount)
		except:
			pass

	def setupMainBar(self, barLength, position=0):
		try:
			wx.CallAfter(self.__setupMainBar, barLength, position)
		except:
			pass


	def pulseMainBar(self, ammount=1):
		try:
			wx.CallAfter(self.__pulseMainProgressBar)
		except:
			pass

	def incMainBar(self, ammount=1):

		try:
			wx.CallAfter(self.__incrementMainProgressBar, ammount)
		except:
			pass

	# miscellaneous print functions. It needs the mainWindow Handle, no where else to put it, really

	def __printColor(self, inString, color):
		textCtrl = self.parentWindow.StatusWin
		r, g, b = color
		textCtrl.SetDefaultStyle(wx.TextAttr(colBack=wx.Colour(r, g, b)))
		try:
			textCtrl.AppendText(inString)
		except UnicodeDecodeError:
			textCtrl.AppendText("Unicode Decoding Error - %s" % urllib2.quote(inString))


		textCtrl.LineDown()
		textCtrl.SetDefaultStyle(wx.TextAttr())

	def printColor(self, string, color=(0, 0, 0)):

		try:
			wx.CallAfter(self.__printColor, string, color)
		except:
			pass


class ConfigValues:				# Passed to webget plugin function

	aList			=	[]
	ovwMode			=	""
	nSrcMode		=	""

	stopChildThreads	=	False

	progBars		= ProgressBars()

	def __init__(self):


		self.pickleFileName		= "configuration.pik"
		self.downloadDir		= wx.GetHomeDir()
		self.load()
		self.clear()

	def clear(self):
		self.aList		=	[]
		self.ovwMode		=	""
		self.nSrcMode		=	""
		self.stopChildThreads	=	False

	def __repr__(self):
		str = "Settings:\n"
		for key, value in self.__dict__.iteritems():
			str += "\t%s - %s\n" % (key, value)

		str += "Persistant Settings:\n"
		for key, value in self.getSettingDict.iteritems():
			str += "\t%s - %s\n" % (key, value)
		return str

	def enumerate(self):
		self.__repr__()



	def dump(self):
		config = self.__dict__
		self.clear()

		try:
			pickleFile = open(self.pickleFileName, "wb")

			pik = cPickle.dumps(config)


			pickleFile.write(pik)
			pickleFile.close()
		except:
			print"Failed to Save Settings"


	def load(self):

		try:
			pickleFile = open(self.pickleFileName, "r")
			self.__dict__ = cPickle.load(pickleFile)
			pickleFile.close()
		except:
			pass			# First run?



	def getSettingDict(self):
		return self.__dict__


	def start(self, parent):

		print "Opening Settings Manager"

		Main = settings.SettingsWin(None, -1, "", parent)
		Main.Show()

		return


	def __del__(self):
		#print "Closing Settings"
		#self.dump()
		pass


if __name__ == "__main__":
	print "test"
	settingsObj = ConfigValues()

	settingsObj.load()
	print settingsObj.getSettingDict()
	#settingsObj.dump()


if __name__ == "__main__":
	configuration = ConfigValues()

